package org.kukker.list;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Map;
import java.util.Properties;

import org.kukker.R;
import org.kukker.activity.SearchEventsActivity;
import org.kukker.activity.widget.FloatingMenu;
import org.kukker.animation.AnimationFactory;
import org.kukker.app.KukkerApp;
import org.kukker.event.Event;
import org.kukker.gesture.G6;

import android.app.Activity;
import android.app.ListActivity;
import android.content.AssetManager;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.IntentReceiver;
import android.content.Resources;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.content.DialogInterface.OnCancelListener;
import android.content.DialogInterface.OnClickListener;
import android.content.Resources.Theme;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.util.MonthDisplayHelper;
import android.view.ContextMenu;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.Menu.Item;
import android.view.View.OnLongClickListener;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;
import android.view.animation.Animation.AnimationListener;
import android.widget.AbsoluteLayout;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.AdapterView.ContextMenuInfo;
import android.widget.ImageView.ScaleType;

public class KukkerListItemView extends LinearLayout implements IKukkerListItemView {
	boolean showdebugmessage = false;
	enum State{
		SELECTED (Background.SELECTED), //in the sense of the underlying data model		
		UNSELECTED (Background.UNSELECTED),//in the sense of the underlying data model
		INFOCUS (Background.INFOCUS), //in the UI sense 
		OUTFOCUS (Background.UNSELECTED), //in the UI sense		
		SAVED (Background.SAVED) //in the sense of the underlying data model
		;
		
		public Background background; 
		
		private State(Background background){
			this.background = background;
		}
	}
	
	enum InterceptMode{
		BASIC;
	}
	
	enum Background{
		SELECTED (R.drawable.purplebutton,Color.BLACK),
		UNSELECTED (R.drawable.overlaygrey,Color.BLACK),
		INFOCUS(R.drawable.greenbutton,Color.BLACK),
		SAVED (R.drawable.flyingnote_faintaqua_alpha,Color.WHITE)
		;
		
		public int DrawableResourceId;
		public int BackgroundColor;
		
		private Background(int drawableResourceId, int backgroundColor){
			this.DrawableResourceId = drawableResourceId;
			this.BackgroundColor = backgroundColor;
		}
		
		public void applyBackground(View view){view.setBackground(this.DrawableResourceId);}
		public void applyBackgroundColor(View view){view.setBackgroundColor(this.BackgroundColor);}
	}
	
	
	enum Icons{		
		UPCOMING (R.drawable.icon_web,0),
		SAVED (R.drawable.icon_save,1);
		
		public int DrawableResourceId;
		public int Position;
		
		private Icons(int drawableResourceId, int position){
			this.DrawableResourceId = drawableResourceId;
			this.Position = position;
		}
		
		public Drawable getDrawable(Context c){
			return c.getResources().getDrawable(this.DrawableResourceId);
		}
	}
	
	
	protected State mState;
	private TextView mTitle;
	private TextView mShortDesc;
	private TextView mLongDesc;
	private TextView mStartDate;
	private TextView mVenueInfo;
	private Spinner s1;
	
	//private Button mDateButton;
	private RelativeLayout mHeader;
	private ImageView mCheckedOut;
	private ArrayList<ImageView> icons;

	private InterceptMode mInterceptMode = InterceptMode.BASIC;
	
	private Rect mRect; 
	protected int mPosition;
	protected KukkerListView mListView;
	
	 
	
	/**
	 * The Floating Menu
	 */
	View v;


	
	private G6 g6;
	
	//TODO: do we need this
	/*
	public void setPosition(int position){
		this.mPosition = position;
	}
	*/
	
	/**
	 * Returns the position of this view in the list view.
	 */
	/*
	public int getPosition(){		
		return this.mPosition;		
	}
	*/
	
	//TODO:restoreStateFromDataModel
	public void restoreUiFromDataModel(){
		
	}
	
	public void saveStateToDataModel(){
		
	}	
	
	/*
	public void drawableStateChanged(){
		Log.i("debug","drawableStateChanged, pos:"+this.mPosition);
	}
	*/
	
	private void updateFieldsText(){
		this.mTitle.setText("");
		this.mShortDesc.setText("");
		this.mLongDesc.setText("");
		this.mStartDate.setText("");		
		
		
	}
	
	
	protected void onPopulateContextMenu(ContextMenu menu){
		Item mi0=	menu.add(0, 0, "Forward to friends");
		Item mi1=	menu.add(0, 0, "Save to phone");
	}
	
	private void setCommonAttributes(View view){
		view.setClickable(false);
		view.setFocusable(false);				
	}

	public void addChildViews(Context context) {
		
		//	add header area
		RelativeLayout.LayoutParams rllp = new RelativeLayout.LayoutParams(300,LayoutParams.WRAP_CONTENT);
		mHeader.addView(mStartDate, rllp);
		//rllp.setMargins(0,0,0,10);
		
		
		//	add icons inside header
		
		{
		RelativeLayout.LayoutParams lp;
		ImageView imV;
		for(int i=0,j=icons.size();i<j;i++){	
			lp = new RelativeLayout.LayoutParams(16,16);
			lp.setMargins(0,0,(16+3)*i, 0);			
			imV = icons.get(i);
			lp.addRule(RelativeLayout.ALIGN_WITH_PARENT_RIGHT,this.mListView.getId());			
			mHeader.addView(imV, lp);
		}
		}
		
		
		mStartDate.setId(1);

		// RelativeLayout mRelLayout = new RelativeLayout(context);
		// addView(mHeader, rllp);

		addView(mHeader, new LinearLayout.LayoutParams(
				LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
		// mHeader.setBackgroundColor(Color.BLUE);
		// addView(mStartDate, new
		// LinearLayout.LayoutParams(LayoutParams.FILL_PARENT,
		// LayoutParams.WRAP_CONTENT));
		addView(mTitle, new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT,
				LayoutParams.WRAP_CONTENT));
		/*
		addView(mLongDesc, new LinearLayout.LayoutParams(
				LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));*/
		addView(mVenueInfo, new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT,
				LayoutParams.WRAP_CONTENT));
		 
		
		s1 = new Spinner(this.mContext);
		s1.setBackground(null);
		s1.setBackgroundColor(android.graphics.Color.TRANSPARENT);
				
		/*
		SpinAd spinad = new SpinAd(this.mContext,0);
		spinad.mContext = this.mContext;
		s1.setAdapter(spinad);
		
		s1.setSelectorSkin(this.getResources().getDrawable(R.drawable.spinner));
		s1.setPadding(0, 0,0,0);
		s1.setPreferredHeight(100);	
		addView(s1,new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT,
				LayoutParams.WRAP_CONTENT) );
		
		*/
		
		
		// addView(mTitle, new
		// LinearLayout.LayoutParams(LayoutParams.FILL_PARENT,
		// LayoutParams.WRAP_CONTENT));
		// addView(mTitle, new
		// LinearLayout.LayoutParams(LayoutParams.FILL_PARENT,
		// LayoutParams.WRAP_CONTENT));
	}
	

	class SpinAd extends ArrayAdapter{
		public Context mContext;
		public SpinAd(Context context, int resource) {
			super(context, resource);
			// TODO Auto-generated constructor stub
			
		}
		public int getCount(){
			
			return 2;
		}
		
		public long getItemId(int position){
			return position;
			
		}
		
		public Object getItem(int position){
			return new Object();
		}
		
		public View getView(int position, View convertView, ViewGroup parent){
			TextView tv = new TextView(mContext);
			//tv.setTextColor(Color.BLACK);
			//tv.setBackgroundColor(Color.TRANSPARENT);
			tv.setText("position:"+position);
			
			if(position==1){
				ImageView im = new ImageView(mContext);
				im.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT));
				im.setImageDrawable(mContext.getResources().getDrawable(R.drawable.snow));
				return im;
			}
			return tv;			
		}
		
		
		
	}
	
	
	public KukkerListItemView(Context context) {
		super(context);		
		this.initializeChildViews(context);
		this.init(context);
	}
	
	/*
	public KukkerListItemView(Context context, Event data) {
		super(context);
		this.mData = data;
		this.initializeChildViews(context);
		this.init(context);
		this.applyDataToWidgets();
		
	}	
	*/
	
	
	public KukkerListItemView(Context context, Event data, KukkerListView listView) {
		super(context);
		
		//initialize variables
		this.mData = data;
		this.mListView = listView;
		this.icons = new ArrayList<ImageView>();
		this.g6 = new G6(this);
		this.mState = State.UNSELECTED;
		
		this.initializeChildViews(context);
		this.init(context);
		this.applyDataToWidgets();
	}
	
	private void init(Context context){
		
		this.setFadingEdgeLength(0);
		this.setFocusableInTouchMode(true); 
				
		this.setOrientation(VERTICAL);
		
		this.setFocusable(true); //somehow i have to add this line otherwise by default the onFocusChanged is not invoked.
		this.setClickable(true); //read above
			
		this.addChildViews(context);		
		this.updateView();
		this.updateFieldsText();
		
		//this.setBackground(R.drawable.greybutton_alpha);
		
		this.setBackground(R.drawable.overlaygrey);
		
		this.setDrawingCacheEnabled(true);
		this.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_LOW);
			
		//context menu
		this.setOnLongClickListener(mOnLongClickListener);
			
	}
	
	

	
	
	

		
		
	private OnLongClickListener mOnLongClickListener = new OnLongClickListener(){

		@Override
		public boolean onLongClick(View arg0) {
			 Log.i("eventflow1",
		    			"["+this.getClass().getSimpleName()+"]" +
		    			
		    			"["+
		    			
		    			"]"
		    			
		    			+"["
		    			
		    			+"onLongClickListener()"  
		    			+", position:"+mPosition
		    			+", isFocused:"+isFocused()  
		    			+", isSelected:"+isSelected()
		    			  			
		    			+"]"
		    			
				 );
				
			return false;
		}
		
	};
	
	/*
	public void setOnLongClickListener(OnLongClickListener l){
		this.mOnLongClickListener = l;
		this.setOnLongClickListener(mOnLongClickListener);
	}
	*/	
	
	private void initializeChildViews(Context c) {

		mTitle = new TextView(c);
		mTitle.setTypeface(Typeface.DEFAULT_BOLD);
		mTitle.setTextColor(Color.BLACK);
		setCommonAttributes(mTitle);
		mTitle.setTextSize(11);
		mTitle.setTextScaleX((float)1.3);
		
		mShortDesc = new TextView(c);
		mShortDesc.setTextColor(Color.BLACK);
		mShortDesc.setTypeface(Typeface.MONOSPACE);
		mShortDesc.setTextScaleX((float)1.3);
		setCommonAttributes(mShortDesc);
		mShortDesc.setTextSize(12);
		
		mLongDesc = new TextView(c);
		mLongDesc.setTextColor(Color.BLACK);
		setCommonAttributes(mLongDesc);		
		//mLongDesc.setAutoLinkMask(Linkify.ALL);
		
		
		mStartDate = new TextView(c);
		mStartDate.setTextSize(13);
		mStartDate.setTextScaleX((float)1.1);
		mStartDate.setTextColor(Color.BLACK);
		mStartDate.setTypeface(Typeface.DEFAULT);
		setCommonAttributes(mStartDate);
		
		mVenueInfo = new TextView(c);
		mVenueInfo.setTextColor(Color.BLACK);
		setCommonAttributes(mVenueInfo);
		mVenueInfo.setTextSize(12);
		
		
		mHeader = new RelativeLayout(c);
		setCommonAttributes(mHeader);
		
		s1 = new Spinner(this.mContext);
		
		/*
		mCheckedOut = new ImageView(c);
		mCheckedOut.setVisibility(ImageView.VISIBLE);
		mCheckedOut.setImageDrawable(c.getResources().getDrawable(
				R.drawable.icon_tag_add));
		mCheckedOut.setScaleType(ScaleType.CENTER);
		*/
		
		//icons
		ImageView icon0 = new ImageView(c);
		icon0.setImageDrawable(c.getResources().getDrawable(R.drawable.transparent_dot));
		icon0.setScaleType(ScaleType.CENTER);
		icon0.setVisibility(ImageView.VISIBLE);
		
		ImageView icon1 = new ImageView(c);
		icon1.setImageDrawable(c.getResources().getDrawable(R.drawable.transparent_dot));
		icon1.setScaleType(ScaleType.CENTER);
		icon1.setVisibility(ImageView.VISIBLE);
		
		icon0.setImageDrawable(this.getResources().getDrawable(R.drawable.icon_save));
		
		this.icons.add(icon0);
		this.icons.add(icon1);
		
		
	}
	
	
	public void setListView(KukkerListView view){
		this.mListView = view;
		
	}


	public boolean onKeyMultiple(int keyCode,int repeatCount, KeyEvent event){
		/*
		Log.i("eventflow1",
    			"["+this.getClass().getSimpleName()+"]" +
    			
    			"["+
    			"isSelected:"+this.isSelected()+
    			"]"
    			
    			+"["
    			+"onKeyMultiple() " +
    			",keyCode:"+keyCode
    			+",position:"+this.mPosition
    			+"]"    			
    	);
		*/
		
		return false;
		
	}
	
	
	public boolean onKeyDown(int keyCode, KeyEvent event){		
		if(showdebugmessage){
		Log.i("eventflow1",
    			"["+this.getClass().getSimpleName()+"]" +
    			
    			"["+    			
    			"]"
    			
    			+"["
    			+"onKeyDown() " 
    			+", position:"+this.mPosition
    			+", keyCode:"+keyCode
    			+", isFocused:"+this.isFocused()
    			+", isSelected:"+this.isSelected()
    			+", repeat:"+event.getRepeatCount()
    			+"]"    			
    	);
		}
		
		
		//boolean res = super.onKeyDown(keyCode, event);
		
		int count = event.getRepeatCount();
		
		if(keyCode == KeyEvent.KEYCODE_DPAD_DOWN){		
			
			//quick scroll mode
			if(count > 2){
				return false;
			}else{//normal mode
				
				return true;	
			}			
		}
		else if(keyCode == KeyEvent.KEYCODE_DPAD_UP){
			
			
			//quick scroll mode
			if(count > 2){
				return false;
			}else{//normal mode
				return true;	
			}		
			
			
		}
		else if(keyCode == KeyEvent.KEYCODE_DPAD_LEFT){		
			return true;	
		}
		
		else if(keyCode == KeyEvent.KEYCODE_DPAD_CENTER){		
			return true;	
		}
		
		
		return false;
		
		/*
		if(keyCode == KeyEvent.KEYCODE_DPAD_LEFT){
			notifyOnListItemKeyLeftDown();
			
			//since we want to detect on key up later we have to stop this event from propagating.
			//stop propagating 
			return true;
		}
		
		if(keyCode == KeyEvent.KEYCODE_DPAD_RIGHT){
			//since we want to detect on key up later we have to stop this event from propagating.
			//so that the next keyup event will be handled by this object.
			return true;
		}
		
		if(keyCode == KeyEvent.KEYCODE_DPAD_CENTER){	
			//since we want to detect on key up later we have to stop this event from propagating.
			//so that the next keyup event will be handled by this object.
			return true;		
		}
		
		if(keyCode == KeyEvent.KEYCODE_DPAD_DOWN){			
			
			//since we want to detect on key up later we have to stop this event from propagating.
			//stop propagating 
			return true;
		}
		
		if(keyCode == KeyEvent.KEYCODE_DPAD_UP){			
			
			//since we want to detect on key up later we have to stop this event from propagating.
			//stop propagating 
			return true;
		}
		
		
		return false;
		*/
    	
	}
	
	public boolean onKeyUp(int keyCode, KeyEvent event){
		if(showdebugmessage){
		Log.i("eventflow1",
    			"["+this.getClass().getSimpleName()+"]" +
    			
    			"["+
    			
    			"]"
    			
    			+"["
    			
    			+"onKeyUp() " 
    			+", position:"+this.mPosition
    			+", keyCode:"+keyCode    		
    			+", isFocused:"+this.isFocused()    	
    			+", isSelected:"+this.isSelected()
    			+", repeat:"+event.getRepeatCount()
    			+"]"    			
    	);
		}

				
		//boolean res = super.onKeyUp(keyCode, event);
		//this.makeSureVisible();
		
		if(keyCode == KeyEvent.KEYCODE_DPAD_DOWN){
			//super.onKeyUp(keyCode, event);
			this.mListView.setSelection(this.mPosition+1);
			
			
			/*
			View v = this.focusSearch(View.FOCUS_DOWN);
			if(v!=null){
				Log.i("eventflow1","focus given to: "+this.getClass().getSimpleName());				
				v.requestFocus();				
				return true;
			}
			*/
			this.mListView.awakenScrollbars(500);
			return false;
		}
		else if(keyCode == KeyEvent.KEYCODE_DPAD_UP){
			//super.onKeyUp(keyCode, event);
			this.mListView.setSelection(this.mPosition-1);
			this.mListView.awakenScrollbars(500);
			
			return false;
			
		}
		
		else if(keyCode == KeyEvent.KEYCODE_DPAD_LEFT){
			notifyOnListItemKeyLeftUp();
			//Log.i("agus",this.mData.name);
			return true;
		}
		else if(keyCode == KeyEvent.KEYCODE_DPAD_RIGHT){
			notifyOnListItemKeyRightUp();
			//Log.i("agus",this.mData.name);
			return true;
		}
		else if(keyCode == KeyEvent.KEYCODE_DPAD_CENTER){			
			notifyOnListItemKeyDCenterClick();
			return true;
		}
		
		return false;
		
		
		
		/*
		//EventListView eventListView = EventListView.getInstance();
		
		
		if(keyCode == KeyEvent.KEYCODE_DPAD_CENTER){		
			//since we want to detect on key up later we have to stop this event from propagating.		
			notifyOnListItemKeyDCenterClick();
			return true;
		}
		
		
		if(keyCode == KeyEvent.KEYCODE_DPAD_LEFT){
			notifyOnListItemKeyLeftUp();
			return true;
		}

		if(keyCode == KeyEvent.KEYCODE_DPAD_RIGHT){
			//since we want to detect on key up later we have to stop this event from propagating.			
			notifyOnListItemKeyRightUp();
			return true;			
		}
		if(keyCode == KeyEvent.KEYCODE_DPAD_DOWN){
			//this.mListView.setSelection(this.mPosition);
			//sets the internal selection pointer of the list view to this item so that the selector will move to this position
			View v = this.focusSearch(View.FOCUS_DOWN);
			if(v!=null){
				Log.i("eventflow1","focus given to: "+this.getClass().getSimpleName());
				
				v.requestFocus();
				return true;
			}
			return false;
		}

		if(keyCode == KeyEvent.KEYCODE_DPAD_UP){
			//this.mListView.setSelection(this.mPosition);
			//sets the internal selection pointer of the list view to this item so that the selector will move to this position
			
			View v = this.focusSearch(View.FOCUS_UP);
			if(v!=null){
				Log.i("eventflow1","focus given to: "+this.getClass().getSimpleName());
				
				v.requestFocus();
				return true;
			}
			return false;
		}
		if(keyCode == 1){//menu button
			//since we want to detect on key up later we have to stop this event from propagating.			
			notifyOnListItemMenuUp();
			return false ;		//let propagate so that the menu is displayed.
		}
		
		

		
		return false;
		*/
	}
	
	
	
	public void setTitle(String title) {
		
		mTitle.setText(title);
	}
	
	
	public void setVenueInfo(String text) {
		
		mVenueInfo.setText(text);
	}
	


	public void setStartDate(String text) {
		//input format: YYYY-MM-DD
		
		this.updateStartDate(text);		
	}

	public void setShortDesc(String text) {
		mShortDesc.setText(text);
	}

	public void setExpanded(boolean expanded) {
		mLongDesc.setVisibility(expanded ? VISIBLE : GONE);
		
	}

	public void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect){
		if(showdebugmessage){
		Log.i("eventflow1",
    			"["+this.getClass().getSimpleName()+"]" +
    			
    			"["+
    			
    			"]"
    			
    			+"["
    			+"onFocusChanged()"
    			+", position:"+this.mPosition
    			+", gainFocus:"+gainFocus
    			+", isSelected:"+this.isSelected()
    			+", direction:"+direction    			
    			+"]"
    			+"value: "+this.mData.name
    			
    	);
		}
		
		//super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
		
		
		if(gainFocus){
			//this.mState = State.INFOCUS;		
			//Log.i("debug","KukkerListItem, onFocusChanged, gainFocus: position:"+this.mPosition);
			this.mListView.setSelection(this.mPosition);
		}else{
			
		}
		
		
	}
	
	
	/*
	public boolean onInterceptTouchEvent(MotionEvent event){
		Log.i("agus","intercept");
		if(!Kukker.F_LISTITEM){
			Log.i("agus","blocked");
			return true;
		}
		else{
			Log.i("agus","unblocked");
			return super.onInterceptTouchEvent(event);
		}
	}
	*/
	


	public boolean onTouchEvent(MotionEvent event) {
		
		super.onTouchEvent(event);
		
		if(showdebugmessage){
		 String actionName = org.kukker.Util.kMotionEvent.getActionName(event);
		 
		 		  
		  
		 Log.i("eventflow1",
    			"["+this.getClass().getSimpleName()+"]" +
    			
    			"["+
    			
    			"]"
    			
    			+"["
    			
    			+"onTouchEvent()"  
    			+", position:"+this.mPosition
    			+", action:"+actionName
    			+", isFocused:"+this.isFocused()  
    			+", isSelected:"+this.isSelected()
    			  			
    			+"]"
    			
		 );
		
		}
		 
		 int action = event.getAction();
		 
		if(this.isSelected() && this.isFocused()){
			Log.i("debug","already selected");
			
			//MotionEvent forwardEvent = new MotionEvent(event.getDownTime(),event.getEventTime(),);
			//ev
			
			
			//this.mListView.dispatchTouchEvent(event);
			return true;
			/*
			if(action == MotionEvent.ACTION_UP){
				return false; //hack for event to propage up for enabling the context menu
			}
			else{//intercept for touch move or down
				return true;
			}
			*/
		}
			
			
		boolean handled[] = this.g6.detect(event);
		Log.i("debug","g6 handled:" + handled[1]);
		
		if(handled[1]){
			this.mListView.mChildItemSelected = this;
			this.mListView.mChildItemIsSelected = true;
			
			this.setSelected(true);
			this.requestFocus();
			this.updateBackground();
			
			if(event.getAction()==MotionEvent.ACTION_UP){
				//position this view so that it is completely visible
				this.makeSureVisible();
				this.setSelected(true);
				this.requestFocus();
				this.updateBackground();
				
				//this.mListView.setSelection(this.mPosition);
				
				
			}
			
			/*
			boolean isf = this.isFocused();
			boolean iss = this.isSelected();
			Log.i("debug","kup - handled:"+handled[1]+",focus:"+isf+", selected:"+iss);
			this.setBackground(EventView.BACKGROUND_SELECTED);
			*/
			//return handled[0];
		}
		
		
		if(action == MotionEvent.ACTION_MOVE){
			return false; //allow to propagate to parent, otherwise would not drag scroll.
		}
	
		else if(action == MotionEvent.ACTION_CANCEL){
			/*
			Background.UNSELECTED.applyBackground(this);
			View aView = this.mListView.findFocus();
			if(aView != null){
				try{
				//((EventView) aView).setBackground(Background.UNSELECTED.DrawableResourceId);
				}catch(Exception e){
					
				}
			}
			*/
			//this.setSelected(false);
			//this.clearFocus();
			
			return true;
		}
		
		
		return true;
	}


	static class Animation{
		
		public TranslateAnimation getFloatingMenuVisibleAnimation() {
			long animationDuration = 500;

			TranslateAnimation translateAnim;
			translateAnim = new TranslateAnimation(-100, 0, 0, 0);
			translateAnim.setDuration(animationDuration);

			FloatingMenuVisibleAnimationListener mal = new FloatingMenuVisibleAnimationListener();
			translateAnim.setAnimationListener(mal);
			return translateAnim;
		}

		public TranslateAnimation getFloatingMenuInvisibleAnimation() {
			long animationDuration = 500;

			TranslateAnimation translateAnim;
			translateAnim = new TranslateAnimation(0, -100, 0, 0);
			translateAnim.setDuration(animationDuration);

			FloatingMenuInvisibleAnimationListener mal = new FloatingMenuInvisibleAnimationListener();
			translateAnim.setAnimationListener(mal);
			return translateAnim;
		}

		class FloatingMenuVisibleAnimationListener implements AnimationListener {
			@Override
			public void onAnimationEnd() {
				Log.i("EventView", "AnimationEnd");
				
				AbsoluteLayout.LayoutParams abslp = new AbsoluteLayout.LayoutParams(
						LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT,
						100, 100);
				FloatingMenu.getInstance().setLayoutParams(abslp);
			}

			@Override
			public void onAnimationRepeat() {
				// TODO Auto-generated method stub
			}

			@Override
			public void onAnimationStart() {
				// TODO Auto-generated method stub
				AbsoluteLayout.LayoutParams abslp = new AbsoluteLayout.LayoutParams(
						LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT,
						0, 100);
				FloatingMenu.getInstance().setLayoutParams(abslp);
				
				FloatingMenu.getInstance().setVisibility(View.VISIBLE);
				FloatingMenu.getInstance().showChildren();
			}
		}
		
		
		class FloatingMenuInvisibleAnimationListener implements AnimationListener {
			@Override
			public void onAnimationEnd() {
				Log.i("EventView", "AnimationEnd");
				AbsoluteLayout.LayoutParams abslp = new AbsoluteLayout.LayoutParams(
						LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT,
						0, 100);
				FloatingMenu.getInstance().setLayoutParams(abslp);
				FloatingMenu.getInstance().setVisibility(View.GONE);
				FloatingMenu.getInstance().hideChildren();
				
				
			}

			@Override
			public void onAnimationRepeat() {
				// TODO Auto-generated method stub
			}

			@Override
			public void onAnimationStart() {
				FloatingMenu.getInstance().setVisibility(View.VISIBLE);
				// TODO Auto-generated method stub
			}
		}

	}
	

	
	private void makeSureVisible(){
		/*
		mRect.set(0,0,this.getMeasuredWidth(),this.getMeasuredHeight()); 
		//it seems that calling this.getMeasuredWidth and getMeasuredHeight will recalculate the dimension due to content changes.
		this.requestRectangleOnScreen(mRect);
		*/
	}

	/**
	 * Update display based on metadata
	 */
	protected void updateBackground(){		
		switch(mState){
		case SELECTED:{
			setBackground(Background.SELECTED.DrawableResourceId);
			break;
		}
		case UNSELECTED:{
			setBackground(Background.UNSELECTED.DrawableResourceId);
			break;	
		}
		case SAVED:{
			setBackground(Background.SAVED.DrawableResourceId);
			
			break;	
		}
		}		
	}
	
	
	protected IKukkerListItemListener mKukkerListItemListener;
	public void setKukkerListItemListener(IKukkerListItemListener listener){
		this.mKukkerListItemListener = listener;
	}	
	
	protected void notifyOnListItemKeyLeftDown(){
		try{
			mKukkerListItemListener.onListItemKeyLeftDown(this);
		}
		catch(Exception e){
			Log.i(this.getClass().getName(),e.getCause()+","+e.getMessage()+" ");
		} 
	}
	
	protected void notifyOnListItemKeyLeftUp(){
		try{
			//this.mListView.clearAllFocus();
			mKukkerListItemListener.onListItemKeyLeftUp(this);
		}
		catch(Exception e){
			Log.i(this.getClass().getName(),e.getMessage()+" ");
		} 
	}
	protected void notifyOnListItemKeyRightUp(){
		try{
			mKukkerListItemListener.onListItemKeyRightUp(this);
		}
		catch(Exception e){
			Log.i(this.getClass().getName(),e.getMessage()+" ");
		} 
	}
	
	protected void notifyOnListItemKeyDCenterClick(){
		try{
			mKukkerListItemListener.onListItemKeyDCenterClick(this);
		}
		catch(Exception e){
			Log.i(this.getClass().getName(),e.getMessage()+" ");
		} 
	}
	
	protected void notifyOnListItemMenuUp(){
		try{
			mKukkerListItemListener.onListItemKeyMenuClick(this);
		}
		catch(Exception e){
			Log.i(this.getClass().getName(),e.getMessage()+" ");
		} 
	}

	
	protected  Event mData; //reference to the data, do not modify data here
	@Override
	public void setData(Event data) {

		this.mData = data;
	}
	public Event getData() {

		return this.mData;
	}

	@Override
	public KukkerListView getListView() {
		return this.mListView;
	}

	@Override
	public int getPosition() {

		return this.mPosition;
	}
	@Override
	public void setPosition(int position) {
		this.mPosition = position;
	}

	
	/**
	 * Updates the view 
	 * 
	 */
	@Override	
	public void updateView() {
		this.syncViewWithModel();
		this.updateBackground();
		this.updateIcons();
		
		//this.updateFieldsText();
	}
	
	/**
	 * Synchronizes the necessary attributes of this view with the underlying data 
	 * so that the displayed view reflects the data
	 */
	public void syncViewWithModel(){
		if(this.mData != null){
			if(this.mData.getIsSaved()){
				this.mState = State.SAVED;
			}else{
				this.mState = State.UNSELECTED;
			}
		}else{
			this.mState = State.UNSELECTED;
		}
	}
	
	private void updateIcons(){
		if(this.mData != null){

			//get icons slot			
			
			ImageView icon0 = icons.get(0);
			ImageView icon1 = icons.get(1);
			
			//set icons
			
			if(this.mData.originId == 1){
				icon0.setImageDrawable(KukkerListView.icon_web);
				icon0.setVisibility(View.VISIBLE);
			}				
			else if(this.mData.originId == 0){				
				icon0.setImageDrawable(KukkerListView.icon_web_disabled);
				icon0.setVisibility(View.VISIBLE);
			}
			
			if(this.mData.getIsSaved()){				
				icon1.setImageDrawable(KukkerListView.icon_saved);			
				icon0.setVisibility(View.VISIBLE);
			}else{
				icon1.setImageDrawable(KukkerListView.icon_saved_disabled);
				icon0.setVisibility(View.VISIBLE);
			}
		}
	}
	
	protected void applyDataToWidgets(){
		
		
		
		
		try{
//		Log.i("debug",this.mData.startDate);
		this.updateTitle();
		this.updateStartDate(this.mData.startDate);
		this.updateVenueInfo();
		}
		catch(Exception e){
			Log.e("error","");
		}
	}
	
	public void updateTitle(){
		this.mTitle.setText(this.mData.name);
	}	
	private void updateVenueInfo(){
		String venueInfo = "";
		if(this.mData.venueName.length() > 0){
			venueInfo += this.mData.venueName;			
		}
		if(this.mData.venueAddress.length() > 0){
			venueInfo += ", ";
			venueInfo += this.mData.venueAddress;
		}
		if(this.mData.venueCity.length() > 0){
			venueInfo += ", ";
			venueInfo += this.mData.venueCity;
		}
		
		this.mVenueInfo.setText(venueInfo);		
	}

	private void updateStartDate(String startDate){
		//input format yyyy-mm-dd
		
		int []dateValues = KukkerApp.decodeDateString(this.mData.startDate);		
	//	Log.i("debug",dateValues[0]+","+dateValues[1]+","+dateValues[2]+", "+this.mData.startDate);
	
		//
		String monthName = KukkerApp.getMonthName(dateValues[1]);
		//Log.i("debug","monthName : "+dateValues[1]+" : "+monthName);
		
		/*
		MonthDisplayHelper mdh = new MonthDisplayHelper(dateValues[0],dateValues[1]);
		int r = mdh.getRowOf(dateValues[2]);
		int c = mdh.getColumnOf(dateValues[2]);
		int d = mdh.getDayAt(r, c);
		int fdom = mdh.getFirstDayOfMonth();
		int wsd = mdh.getWeekStartDay();
		int offset = mdh.getOffset();		
		
		//String dow = android.util.DateUtils.getDayOfWeekStr(d);
		Log.i("debug","rcd:"+r+","+c+","+d);
		
		//Log.i("debug","day of the week: "+dow);
		String dayName ="";
				
		Log.i("debug","rcd,wsd,fdom,offset:"+r+","+c+","+d+","+wsd+","+fdom+","+offset);
		
		int cc =  c;
		int mapi = 1; 
		//mapped index; we normalize, we know the mapping by manually looking at known reference calendar values and comparing it the the column index returned by MonthDisplayHelper 
		int ii = (cc + 5)%7;
		
		if(cc==1){
			mapi = 6; //saturday
			
		}
		if(cc==2){
			mapi = 7; //sunday
			
		}

		if(cc==3){
			mapi = 1; //monday
			
		}

		if(cc==4){
			mapi = 2; //tuesday
			
		}

		if(cc==5){
			mapi = 3; //wednesday
			
		}

		if(cc==6){
			mapi = 4; //thursday
			
		}

		if(c==0){
			mapi = 5; //friday
			
		}
		
		//Now get the day names;
		
		mapi = (cc)%7;
		
			
		if(mapi==5){
			dayName = "Monday";
		}

		if(mapi==6){
			dayName = "Tuesday";
		}

		if(mapi==0){
			dayName = "Wednesday";
		}

		if(mapi==1){
			dayName = "Thursday";
		}

		if(mapi==2){
			dayName = "Friday";
		}

		if(mapi==3){
			dayName = "Saturday";
		}*/
	
		String startTime = "";
		startDate = monthName+" "+dateValues[2]+", "+dateValues[0];
		if(this.mData.startTime != null && this.mData.startTime.length() > 0){
			startDate += " - time: " +this.mData.startTime;
		}
		
		this.mStartDate.setText(startDate);
	}
	
	private boolean int0_keyUp (int keyCode, KeyEvent event){
		if(keyCode == KeyEvent.KEYCODE_DPAD_DOWN){
			View v = this.focusSearch(View.FOCUS_DOWN);
			if(v!=null){
				//Log.i("eventflow1","focus given to: "+this.getClass().getSimpleName());				
				v.requestFocus();				
				return true;
			}
			this.mListView.awakenScrollbars(500);
			
			return false;
		}
		else if(keyCode == KeyEvent.KEYCODE_DPAD_UP){
				View v = this.focusSearch(View.FOCUS_UP);
				if(v!=null){
					Log.i("eventflow1","focus given to: "+this.getClass().getSimpleName());				
					v.requestFocus();				
					return true;
				}
				
				this.mListView.awakenScrollbars(500);
				
				return false;
		}
		
		return true;
		
	}
	
	private boolean int0_keyDown (int keyCode, KeyEvent event){
		
		boolean res = super.onKeyDown(keyCode, event);		
		int count = event.getRepeatCount();
		
		if(keyCode == KeyEvent.KEYCODE_DPAD_DOWN){
			
			
			
			return true;	
		}
		else if(keyCode == KeyEvent.KEYCODE_DPAD_UP){
		
			
			return true;	
		}
		
		
		
		return false;
	}
	
	private boolean int0_onTouchEvent (MotionEvent event){
		super.onTouchEvent(event);
		String actionName = org.kukker.Util.kMotionEvent.getActionName(event);
		
		if(this.isSelected()){
			//Log.i("debug","already selected");
			return true;
		}
			
		boolean handled[] = this.g6.detect(event);
		Log.i("debug","g6 handled:" + handled[1]);
		
		if(handled[1]){
			this.mListView.mChildItemSelected = this;
			this.mListView.mChildItemIsSelected = true;
			
			this.setSelected(true);
			this.requestFocus();
			this.updateBackground();
			
			if(event.getAction()==MotionEvent.ACTION_UP){
				
				//boolean isContextMenuShown = this.mListView.getContextMenuWatcher().isContextMenuShown();
				//if(!isContextMenuShown){
					
					//position this view so that it is completely visible
					this.makeSureVisible();
					this.setSelected(true);
					this.requestFocus();
					this.updateBackground();
					
					//this.mListView.setSelection(this.mPosition);
					
				//}
				
				
				
			}
			
			/*
			boolean isf = this.isFocused();
			boolean iss = this.isSelected();
			Log.i("debug","kup - handled:"+handled[1]+",focus:"+isf+", selected:"+iss);
			this.setBackground(EventView.BACKGROUND_SELECTED);
			*/
			//return handled[0];
		}
		
		if(event.getAction()==MotionEvent.ACTION_MOVE){
			return false; //allow to propagate to parent, otherwise would not drag scroll.
		}
		
		if(event.getAction()==MotionEvent.ACTION_CANCEL){
			/*
			Background.UNSELECTED.applyBackground(this);
			View aView = this.mListView.findFocus();
			if(aView != null){
				try{
				//((EventView) aView).setBackground(Background.UNSELECTED.DrawableResourceId);
				}catch(Exception e){
					
				}
			}
			*/
			//this.setSelected(false);
			//this.clearFocus();
			
			return true;
		}
		
		
		return true;
		
	}
	
	private void int0_onFocusChanged (boolean gainFocus, int direction, Rect previouslyFocusedRect){

		super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
				
		if(gainFocus){
			this.mState = State.INFOCUS;		
			Log.i("debug","KukkerListItem, onFocusChanged, gainFocus: position:"+this.mPosition);
			this.mListView.setSelection(this.mPosition);
		}else{
			
		}
		
	}

	@Override
	public void right() {
		// TODO Auto-generated method stub
		//Log.i("debug","right press");
		//s1.performClick();
		int pos = s1.getSelectedItemPosition();
		int count = s1.getAdapter().getCount();
		if(pos < count){
			s1.setSelection(pos+1,true);			
		}else{
			s1.setSelection(0,true);			
		}
		//s1.requestFocus();
		//s1.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP,KeyEvent.KEYCODE_DPAD_RIGHT));
		
	}
	
	
	
	
} // end of class






